#include "HttpRequest.h"
#include "./common/YXConstant.h"
#include "Http.h"
#include "HttpFixedResponse.h"
#include "HttpResponse.h"
#include "Server.h"

#include <ctype.h>
#include <string.h>

Request *create_request() {
    Request *request        = malloc(sizeof(Request));
    request->state          = HTTP_REQUEST_STATE_PARSE_LINE;
    request->route_state    = ROUTE_DEFAULT_STATE;
    request->method         = sds_create_empty(HTTP_REQUEST_METHOD_MAX_LENGTH);
    request->path           = sds_create_empty(HTTP_REQUEST_PATH_MAX_LENGTH);
    request->content_type   = sds_create_empty(HTTP_REQUEST_CONTENT_TYPE_MAX_LENGTH);
    request->token          = sds_create_empty(HTTP_REQUEST_TOKEN_MAX_LENGTH);
    request->content_length = -1;
    request->body           = sds_create_empty(HTTP_REQUEST_BODY_BUFFER_INIT_SIZE);
    request->bodypos        = 0;
    request->parsed_data      = NULL;

    return request;
}

void reset_request(Request *request) {
    request->state       = HTTP_REQUEST_STATE_PARSE_LINE;
    request->route_state = ROUTE_DEFAULT_STATE;
    sds_clear(request->method);
    sds_clear(request->path);
    sds_clear(request->token);
    sds_clear(request->content_type);
    request->content_length = -1;
    sds_clear(request->body);
    request->bodypos = 0;
    // if (request->parsed_data != NULL) {
    //     cJSON_Delete(request->json_body);
    //     request->json_body = NULL;
    // }
}

void free_request(Request *request) {
    sds_free(request->method);
    sds_free(request->token);
    sds_free(request->path);
    sds_free(request->content_type);
    sds_free(request->body);
    // if (request->json_body != NULL) {
    //     cJSON_Delete(request->json_body);
    // }
    free(request);
}

void parse_request(EventLoop *el, Client *client) {
    Request *request = client->request;

    switch (request->state) {
        case HTTP_REQUEST_STATE_PARSE_LINE: {
            if (parse_http_request_line(el, client) == YX_OK) {
                request->state = HTTP_REQUEST_STATE_PARSE_HEADER;
            }
            break;
        }
        case HTTP_REQUEST_STATE_PARSE_HEADER: {
            if (parse_http_request_header(el, client) == YX_OK) {
                if (request->content_length > 0) {
                    request->state = HTTP_REQUEST_STATE_PARSE_BODY;
                } else {
                    // 正常来说目前已经确定读取请求结束了
                    net_delete_file_event(el, client->fd, YX_NET_READABLE);
                    request->state = HTTP_REQUEST_STATE_PARSE_COMPLETED;
                    do_request(el, client);
                    do_response(el, client);
                }
            }
            break;
        }
        case HTTP_REQUEST_STATE_PARSE_BODY: {
            if (parse_http_request_body(el, client) == YX_OK) {
                // 此刻不一定请求已经读取完毕
                if (do_request(el, client) == YX_OK) {
                    net_delete_file_event(el, client->fd, YX_NET_READABLE);
                    request->state = HTTP_REQUEST_STATE_PARSE_COMPLETED;
                    do_response(el, client);
                }
            }
            break;
        }
        default: {
        }
    }
}

int do_request(EventLoop *el, Client *client) {
    Request  *request  = client->request;
    Response *response = client->response;
    /* 在请求（控制层）之前 */

    if (strcmp(request->method, "GET") == 0) {
        // 特殊处理根路径
        if (strcmp(request->path, "/") == 0) {
            response->content_type = MIME_TYPE_HTML;
            sds_cat(response->body, "<html><body><h1>Hello, World!</h1></body></html>");
        } else {
            get_file(request, response);
        }
    } else if (strcmp(request->method, "POST") == 0) {
        // 特殊处理根路径
        if (strcmp(request->path, "/") == 0) {
            set_response_bad_request(response, "You can't post to root path");
        } else {
            if (post_file(request, response) == YX_ERR)
                return YX_ERR;
        }
    } else {
        set_response_bad_request(response, "Method Not Allowed");
    }
    return YX_OK;
}

int parse_http_request_line(EventLoop *el, Client *client) {
    Request *request = client->request;
    sds      buf     = client->input_buffer;
    sds      method  = request->method;
    sds      path    = request->path;

    int i = 0, j = 0;
    int size = sds_len(buf);

    while (!isspace(buf[i]) && i < size && i < sds_free_len(method)) {
        method[i] = buf[i];
        i++;
    }
    if (i == sds_free_len(method) || i == size) {
        send_response_bad_request(el, client, "Reuqest method is too long");
        return YX_ERR;
    }
    j = i;
    sds_incr_len(method, i);

    i = 0;
    while (isspace(buf[j]) && j < size) {
        j++;
    }
    while (!isspace(buf[j]) && j < size && i < sds_free_len(path)) {
        path[i] = buf[j];
        i++;
        j++;
    }
    if (i == sds_free_len(path) || j == size) {
        send_response_bad_request(el, client, "Reuqest path is too long");
        return YX_ERR;
    }
    sds_incr_len(path, i);
    sds_clear(buf);

    return YX_OK;
}

/**
 * 可以通过判断request的state来决定是否需要继续读取请求体
 */
int parse_http_request_header(EventLoop *el, Client *client) {
    Request *request = client->request;
    sds      buf     = client->input_buffer;

    if (buf[0] == '\n') {
        return YX_OK;
    }
    if (strncmp("Content-Length:", buf, 15) == 0) {
        request->content_length = atoi(buf + 16);
    } else if (strncmp("Content-Type:", buf, 13) == 0) {
        sds_cat_len(request->content_type, buf + 14, sds_len(buf) - 15);
    } else if (strncmp("Authorization:", buf, 14) == 0) {
        sds_cat_len(request->token, buf + 22, sds_len(buf) - 23);
    }
    sds_clear(buf);
    return YX_ERR;
}

int parse_http_request_body(EventLoop* el, Client* client) {
    return YX_OK;
}
